#include <iostream>
#include <memory>

using std::cout;
using std::endl;
using std::shared_ptr;

class Point
    : public std::enable_shared_from_this<Point>
{
private:
    int _x{};
    int _y{};

public:
    Point() { cout << "Point()" << endl; }
    Point(int x, int y) : _x{x}, _y{y} { cout << "Point(int, int)" << endl; }

    void show()
    {
        cout << "{" << _x << ", " << _y << "}" << endl;
    }
    shared_ptr<Point> getShared()
    {
        return shared_ptr<Point>(this);
    }
    shared_ptr<Point> getSharedByEnable()
    {
        return shared_from_this();
    }

    Point *get()
    {
        return this;
    }
};

void printPtr(shared_ptr<Point> ptr)
{
    cout << "addr = " << ptr.get() << ", count = " << ptr.use_count() << endl;
}

void test()
{
    Point *p = new Point(10, 10);
    // cout << "p addr = " << p << endl;
    // shared_ptr<Point> sp1 = std::make_shared<Point>(*p);

    // shared_ptr<Point> sp2 = sp1->getSharedByMake();

    // shared_ptr<Point> sp2 = sp1;
    // sp1->show();
    // sp2->show();

    // cout << "-----------------------" << endl;
    // // shared_ptr<Point> sp3 = sp1->getShared();
    // // sp3->show();

    // shared_ptr<Point> sp4 = sp1->getSharedByEnable();
    // sp4->show();

    // shared_ptr<Point> sp5(sp1->get());
    // sp5->show();

    shared_ptr<Point> sp3 = std::make_shared<Point>(10, 20);
    sp3->show();
    cout << "sp3.get()" << sp3.get() << endl;
}

int main(int args, char *argv[])
{
    test();
    return 0;
}